using System.Collections;
using System.Xml;
using MessageGateway;
using Router;

namespace MessageFilter
{
    public delegate void OnValidationFailedEvent (XmlDocument msg);

    /*
     * This component implements the Message Filter patterns. It forwards a message
     * if the XPath expression evaluates to true. Otherwise it discards the message.
     * A Message Filter is a special case of a Router and is implemented as such.
     */

    public class MessageFilterComponent 
	{
        private OnValidationFailedEvent validationFailedEvent;
        private RouterComponent router;

		public MessageFilterComponent(IMessageReceiver input, IMessageSender output, string validationExpression)
        {
            // forward matching messages
		    MessageDestination dest1 = new MessageDestination(validationExpression, output);
            // discard non matching messages
            MessageDestination dest2 = new MessageDestination(new NullChannel());
		    IList destinations = new ArrayList();
            destinations.Add(dest1);
            destinations.Add(dest2);

            router = new RouterComponent(input, destinations);
            router.AddEventHandler(new OnRouterEvent(OnMessage));
            validationFailedEvent = new OnValidationFailedEvent(NullEvent);
        }

        public MessageFilterComponent(string input, string output, string validationExpression, IMessageGatewayFactory factory) :
            this (factory.GetReceiverInstance(input), factory.GetSenderInstance(output), validationExpression)
        {}

        public void AddEventHandler(OnMsgEvent handler)
        {
            router.AddEventHandler(handler);
        }

        public void  AddEventHandler (OnValidationFailedEvent handler)
        {
            validationFailedEvent += handler;
        }

        private void OnMessage (XmlDocument msg, int pathChosen)
        {
            // fire an event for messages that were not forwarded
            if (pathChosen == 1)
            {
                validationFailedEvent(msg);    
            }
        }

        private void NullEvent (XmlDocument message)
        {
        }
	}
}
